﻿namespace Jhong.FunMVC.Razor
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Text.RegularExpressions;

    internal class View
    {
        private ViewResult _viewResult;

        public View(ViewResult viewResult)
        {
            this._viewResult = viewResult;
        }

        internal static readonly string RootPath = GetRootPath();

        private static string GetRootPath()
        {
            var path = AppDomain.CurrentDomain.GetData(".appPath").ToString();
            if (string.IsNullOrWhiteSpace(path)) path = Environment.CurrentDirectory;
            return path;
        }

        private string FindView()
        {
            var searchPathSb = new StringBuilder();
            for (int i = 0; i < SearchPath.Count(); i++)
            {
                var p = SearchPath[i].TrimStart(new char[] { '/', '\\' });
                var cshtmlPath1 = Path.Combine(RootPath, p, this._viewResult.ControllerName, this._viewResult.ViewName + ".cshtml");
                searchPathSb.AppendLine(Path.Combine(p, this._viewResult.ControllerName, this._viewResult.ViewName + ".cshtml"));
                searchPathSb.AppendLine("<br/>");
                if (File.Exists(cshtmlPath1)) return cshtmlPath1;
                var cshtmlPath2 = Path.Combine(RootPath, p, this._viewResult.ViewName + ".cshtml");
                searchPathSb.AppendLine(Path.Combine(p, this._viewResult.ViewName + ".cshtml"));
                searchPathSb.AppendLine("<br/>");
                if (File.Exists(cshtmlPath1)) return cshtmlPath2;

                var htmlPath1 = Path.Combine(RootPath, p, this._viewResult.ControllerName, this._viewResult.ViewName + ".html");
                searchPathSb.AppendLine(Path.Combine(p, this._viewResult.ControllerName, this._viewResult.ViewName + ".html"));
                searchPathSb.AppendLine("<br/>");
                if (File.Exists(htmlPath1)) return htmlPath1;

                var htmlPath2 = Path.Combine(RootPath, p, this._viewResult.ViewName + ".html");
                searchPathSb.AppendLine(Path.Combine(p, this._viewResult.ViewName + ".html"));
                searchPathSb.AppendLine("<br/>");
                if (File.Exists(htmlPath1)) return htmlPath2;
            }
            throw new FileNotFoundException(string.Format("找不到文件，搜索路径：<br/>{0}", searchPathSb));
        }

        internal static IList<string> SearchPath = new List<string>() {
        "Views",
        Path.Combine("Views","Shared")
        };

        private void Init()
        {
            var rView = this.FindView();
            var rvHtml = File.ReadAllText(rView);

            var layout = this.FindLayout(rvHtml);
            if (null == layout)
            {
                this._outPutHTML.Append(rvHtml);
            }
            else
            {
                var layoutHtml = File.ReadAllText(Path.Combine(RootPath, layout.TrimStart('/')));
                var renderBody = this.FindRenderBody(layoutHtml);
                this._outPutHTML.Append(layoutHtml);
                if (null != renderBody) this._outPutHTML.Replace(renderBody, rvHtml);
            }
        }

        private string FindRenderBody(string layoutVIewHtml)
        {
            var pattern = @"@.*RenderBody\(\)";
            if (false == Regex.IsMatch(layoutVIewHtml, pattern)) return null;
            var mathcs = Regex.Match(layoutVIewHtml, pattern);
            return mathcs.Groups[0].Value;
        }

        private string FindLayout(string pageHtml)
        {
            var pattern = @"RazorHTMLHelper\.Layout\s*=\s*" + "\"" + "(.*)" + "\"" + ";";
            if (false == Regex.IsMatch(pageHtml, pattern)) return null;
            var matches = Regex.Match(pageHtml, pattern);
            return matches.Groups[1].Value;
        }

        private StringBuilder _outPutHTML = new StringBuilder();

        public string GetTempalteHtml()
        {
            this.Init();
            this._outPutHTML.Replace("@ViewData", "@Model." + DynamicViewDataDictionary.InnerViewDataReplaceStr);
            return this._outPutHTML.ToString();
        }
    }
}